﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace Black.Surface2DEngine.Common
{
    /// <summary>
    /// Permet de gérer les threads dans un processus update ou draw
    /// </summary>
    public class ThreadManager
    {
        #region Variables d'instances

        private List<WaitHandle> m_oWaitHandles;

        #endregion

        #region Constructeurs

        /// <summary>
        /// Constructeur de la classe
        /// </summary>
        public ThreadManager()
        {
            // Définition des bornes Thread

            ThreadPool.SetMinThreads(0, 0);
            ThreadPool.SetMaxThreads(6, 6);

            // Initialisation

            this.m_oWaitHandles = new List<WaitHandle>();
        }

        #endregion

        #region Fonctions publiques

        /// <summary>
        /// Lance un traitement asynchrone
        /// </summary>
        /// <param name="p_oProcessHandler">Fonction de début de traitement</param>
        public void StartThread(ThreadItem p_oItem)
        {
            // Ajout du WaitHandle

            this.m_oWaitHandles.Add(new AutoResetEvent(false));

            // On démmare le Thread

            ThreadPool.QueueUserWorkItem(new WaitCallback(p_oItem.Start), this.m_oWaitHandles[this.m_oWaitHandles.Count - 1]);
        }

        /// <summary>
        /// Se met en attente pour définir un point de synchronisation
        /// </summary>
        public void SyncPoint()
        {
            if ( this.m_oWaitHandles.Count > 0 )
            {
                // On attend la fin de tous les Threads

                WaitHandle.WaitAll(this.m_oWaitHandles.ToArray());

                // On vide la liste

                this.m_oWaitHandles.Clear();
            }
        }

        #endregion

        #region Indexer

        /// <summary>
        /// Retourne le nombre de Threads en court d'éxécution
        /// </summary>
        public int Count
        {
            get
            {
                return (this.m_oWaitHandles.Count);
            }
        }

        #endregion
    }
}
